package com.movie.service.impl;

import com.movie.dto.UserMovieStatsDTO;
import com.movie.entity.Movie;
import com.movie.entity.Order;
import com.movie.entity.Seat;
import com.movie.entity.User;
import com.movie.exception.ResourceNotFoundException;
import com.movie.mapper.MovieMapper;
import com.movie.mapper.OrderMapper;
import com.movie.mapper.UserMapper;
import com.movie.service.OrderService;
import com.movie.service.SeatService;
import com.movie.service.ShowtimeService;
import com.movie.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private UserService userService;

    @Autowired
    private ShowtimeService showtimeService;

    @Override
    @Transactional
    public Order createOrder(Order order) {
        Assert.notNull(order, "Order object cannot be null");
        Assert.notNull(order.getUserId(), "User ID cannot be null");
        Assert.notNull(order.getPrice(), "Price cannot be null");
        Assert.notNull(order.getMovieId(), "Movie ID cannot be null");
        Assert.notNull(order.getShowtimeId(), "Showtime ID cannot be null");
        Assert.hasText(order.getSeatInfo(), "Seat info cannot be empty");
        Assert.hasText(order.getOrderNumber(), "Order number cannot be empty");

        User user = userMapper.findById(order.getUserId());
        if (user == null) {
            throw new ResourceNotFoundException("User not found with id: " + order.getUserId());
        }

        order.setOrderTime(LocalDateTime.now());
        order.setStatus(0);
        orderMapper.insert(order);

        // 更新场次可用座位数量
        showtimeService.updateAvailableSeats(order.getShowtimeId());

        return order;
    }

    @Override
    public List<Order> getOrdersByUserId(Long userId) {
        Assert.notNull(userId, "User ID cannot be null");
        return orderMapper.findByUserId(userId);
    }

    @Override
    public int countOrdersByUserId(Long userId) {
        Assert.notNull(userId, "User ID cannot be null");
        return orderMapper.countByUserId(userId);
    }

    @Override
    public Order getOrderById(Long orderId) {
        Assert.notNull(orderId, "Order ID cannot be null");
        Order order = orderMapper.findById(orderId);
        if (order == null) {
            throw new ResourceNotFoundException("Order not found with id: " + orderId);
        }
        return order;
    }

    @Override
    @Transactional
    public Order updateOrderStatus(Long id, Integer status) {
        Assert.notNull(id, "Order ID cannot be null");
        Assert.notNull(status, "Status cannot be null");
        Order order = getOrderById(id);
        int updatedRows = orderMapper.updateStatus(id, status);
        if (updatedRows == 0) {
            throw new RuntimeException("Failed to update status for order with id: " + id);
        }
        order.setStatus(status);
        return order;
    }

    @Override
    @Transactional
    public void cancelOrder(Long orderId) {
        Assert.notNull(orderId, "Order ID cannot be null");
        Order order = getOrderById(orderId);

        if (order.getStatus() != 0) {
            throw new IllegalStateException("Order cannot be cancelled in its current state: " + order.getStatus());
        }

        // 先释放订单占用的座位
        releaseOrderSeats(order);

        int updatedRows = orderMapper.updateStatus(orderId, 2);
        if (updatedRows == 0) {
            throw new RuntimeException("Failed to cancel order with id: " + orderId + ". It might have been updated or deleted.");
        }
    }

    @Override
    public List<Order> findOrdersWithFilters(String orderNumber, String username, LocalDate startDate, LocalDate endDate) {
        return orderMapper.search(orderNumber, username, startDate, endDate);
    }

    @Override
    public List<Order> getAllOrders() {
        return orderMapper.findAll();
    }

    @Override
    public Map<String, Object> getAllOrdersPaged(int page, int size) {
        Assert.isTrue(page >= 0, "Page number must be greater than or equal to 0");
        Assert.isTrue(size > 0, "Page size must be greater than 0");

        int offset = page * size;

        List<Order> orders = orderMapper.findAllPaged(offset, size);
        int total = orderMapper.countAll();

        Map<String, Object> result = new HashMap<>();
        result.put("content", orders);
        result.put("totalElements", total);
        result.put("page", page);
        result.put("size", size);
        result.put("totalPages", total == 0 ? 0 : (int) Math.ceil((double) total / size));
        return result;
    }

    @Autowired
    private SeatService seatService;

    @Override
    @Transactional
    public int cancelTimeoutOrders() {
        // 计算30分钟前的时间点
        LocalDateTime cutoffTime = LocalDateTime.now().minusMinutes(30);

        // 查找所有超过30分钟未支付的订单
        List<Order> timeoutOrders = orderMapper.findUnpaidOrdersOlderThan(cutoffTime);

        int deletedCount = 0;
        for (Order order : timeoutOrders) {
            try {
                // 先释放订单占用的座位
                releaseOrderSeats(order);

                // 然后从数据库中删除超时订单
                int deletedRows = orderMapper.deleteById(order.getId());
                if (deletedRows > 0) {
                    deletedCount++;
                    System.out.println("自动删除超时订单: " + order.getOrderNumber() + ", 下单时间: " + order.getOrderTime());
                }
            } catch (Exception e) {
                // 记录错误但继续处理其他订单
                System.err.println("删除订单 " + order.getId() + " 失败: " + e.getMessage());
            }
        }

        return deletedCount;
    }

    /**
     * 释放订单占用的座位
     * @param order 订单对象
     */
    private void releaseOrderSeats(Order order) {
        if (order == null || order.getSeatInfo() == null || order.getShowtimeId() == null) {
            return;
        }

        try {
            // 获取该场次的所有座位
            List<Seat> seats = seatService.getSeatsByShowtimeId(order.getShowtimeId());
            if (seats == null || seats.isEmpty()) {
                return;
            }

            // 解析座位信息，格式为：行排列号,行排列号,...
            String[] seatInfoArray = order.getSeatInfo().split(",");
            for (String seatInfo : seatInfoArray) {
                // 提取行和列信息
                if (seatInfo.contains("排") && seatInfo.contains("号")) {
                    String rowStr = seatInfo.substring(0, seatInfo.indexOf("排"));
                    String colStr = seatInfo.substring(seatInfo.indexOf("排") + 1, seatInfo.indexOf("号"));

                    try {
                        int rowIndex = Integer.parseInt(rowStr) - 1; // 前端显示从1开始，数据库从0开始
                        int colIndex = Integer.parseInt(colStr) - 1; // 前端显示从1开始，数据库从0开始

                        // 查找对应的座位并释放
                        for (Seat seat : seats) {
                            if (seat.getRowIndex() == rowIndex && seat.getColumnIndex() == colIndex) {
                                seatService.updateSeatStatus(seat.getId(), Seat.STATUS_AVAILABLE);
                                System.out.println("释放座位: 场次ID=" + order.getShowtimeId() + ", 座位=" + (rowIndex+1) + "排" + (colIndex+1) + "号");
                                break;
                            }
                        }
                    } catch (NumberFormatException e) {
                        System.err.println("解析座位信息失败: " + seatInfo + ", " + e.getMessage());
                    }
                }
            }

            // 更新场次可用座位数量
            showtimeService.updateAvailableSeats(order.getShowtimeId());
        } catch (Exception e) {
            System.err.println("释放订单座位失败: 订单ID=" + order.getId() + ", " + e.getMessage());
        }
    }

    @Override
    @Transactional
    public Order payOrder(Long orderId, String username) {
        // 验证参数
        Assert.notNull(orderId, "订单ID不能为空");
        Assert.hasText(username, "用户名不能为空");

        // 获取订单信息
        Order order = getOrderById(orderId);
        if (order == null) {
            throw new ResourceNotFoundException("订单不存在: " + orderId);
        }

        // 检查订单状态
        if (order.getStatus() != 0) {
            throw new IllegalStateException("订单状态不正确，无法支付。当前状态: " + order.getStatus());
        }

        // 获取用户信息
        User user = userService.findByUsername(username);
        if (user == null) {
            throw new ResourceNotFoundException("用户不存在: " + username);
        }

        // 检查用户ID是否匹配订单
        if (!user.getId().equals(order.getUserId())) {
            throw new IllegalStateException("无权支付此订单");
        }

        // 检查余额是否足够
        BigDecimal orderPrice = order.getPrice();
        if (user.getBalance().compareTo(orderPrice) < 0) {
            throw new IllegalStateException("余额不足，请先充值");
        }

        // 扣减用户余额
        userService.deductBalance(user.getId(), orderPrice);

        // 更新订单状态为已支付
        order = updateOrderStatus(orderId, 1);

        return order;
    }

    @Override
    @Transactional
    public List<Order> batchPayOrders(List<Long> orderIds, String username) {
        // 验证参数
        Assert.notEmpty(orderIds, "订单ID列表不能为空");
        Assert.hasText(username, "用户名不能为空");

        // 获取用户信息
        User user = userService.findByUsername(username);
        if (user == null) {
            throw new ResourceNotFoundException("用户不存在: " + username);
        }

        // 获取所有订单并验证
        List<Order> orders = new ArrayList<>();
        BigDecimal totalAmount = BigDecimal.ZERO;

        for (Long orderId : orderIds) {
            Order order = getOrderById(orderId);

            // 检查订单状态
            if (order.getStatus() != 0) {
                throw new IllegalStateException("订单状态不正确，无法支付。订单号: " + order.getOrderNumber() + ", 状态: " + order.getStatus());
            }

            // 检查用户ID是否匹配订单
            if (!user.getId().equals(order.getUserId())) {
                throw new IllegalStateException("无权支付订单: " + order.getOrderNumber());
            }

            orders.add(order);
            totalAmount = totalAmount.add(order.getPrice());
        }

        // 检查余额是否足够
        if (user.getBalance().compareTo(totalAmount) < 0) {
            throw new IllegalStateException("余额不足，请先充值");
        }

        // 扣减用户余额
        userService.deductBalance(user.getId(), totalAmount);

        // 更新所有订单状态为已支付
        List<Order> paidOrders = new ArrayList<>();
        for (Order order : orders) {
            Order paidOrder = updateOrderStatus(order.getId(), 1);
            paidOrders.add(paidOrder);
        }

        return paidOrders;
    }

    @Override
    public UserMovieStatsDTO getUserMovieStats(Long userId) {
        Assert.notNull(userId, "用户ID不能为空");

        // 创建返回对象
        UserMovieStatsDTO stats = new UserMovieStatsDTO();

        // 1. 获取总观影次数
        int totalWatchCount = orderMapper.countByUserId(userId);
        stats.setTotalWatchCount(totalWatchCount);

        // 2. 获取总消费金额
        BigDecimal totalSpent = orderMapper.getTotalSpentByUserId(userId);
        stats.setTotalSpent(totalSpent != null ? totalSpent : BigDecimal.ZERO);

        // 3. 获取电影类型分布
        List<Map<String, Object>> genreDistribution = orderMapper.getGenreDistributionByUserId(userId);
        Map<String, Integer> genreMap = new HashMap<>();
        for (Map<String, Object> item : genreDistribution) {
            String genre = (String) item.get("genre");
            if (genre != null && !genre.isEmpty()) {
                Integer count = ((Number) item.get("count")).intValue();
                genreMap.put(genre, count);
            }
        }
        stats.setGenreDistribution(genreMap);

        // 4. 获取观影时间分布
        List<Map<String, Object>> timeDistribution = orderMapper.getWatchTimeDistributionByUserId(userId);
        Map<String, Integer> timeMap = new HashMap<>();
        for (Map<String, Object> item : timeDistribution) {
            String month = (String) item.get("month");
            if (month != null && !month.isEmpty()) {
                Integer count = ((Number) item.get("count")).intValue();
                timeMap.put(month, count);
            }
        }
        stats.setWatchTimeDistribution(timeMap);

        // 5. 获取最近的观影记录
        List<Order> recentOrders = orderMapper.getRecentWatchesByUserId(userId, 5); // 获取最近5条记录
        List<UserMovieStatsDTO.RecentWatchRecord> recentWatches = new ArrayList<>();

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");

        for (Order order : recentOrders) {
            UserMovieStatsDTO.RecentWatchRecord record = new UserMovieStatsDTO.RecentWatchRecord();
            record.setOrderId(order.getId());

            if (order.getMovie() != null) {
                record.setMovieTitle(order.getMovie().getTitle());
            }

            if (order.getShowtime() != null) {
                record.setHallName(order.getShowtime().getHallName());
                if (order.getShowtime().getShowTime() != null) {
                    record.setWatchTime(order.getShowtime().getShowTime().format(formatter));
                }
            }

            record.setPrice(order.getPrice());
            recentWatches.add(record);
        }

        stats.setRecentWatches(recentWatches);

        return stats;
    }
}